home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / UGPRG.ZIP / DENTHOR / TUT12.DOC < prev    next >
Encoding:
Text File  |  1996-07-27  |  31.9 KB  |  955 lines

  1.                    ╒═══════════════════════════════╕
  2.                    │         W E L C O M E         │
  3.                    │  To the VGA Trainer Program   │ │
  4.                    │              By               │ │
  5.                    │      DENTHOR of ASPHYXIA      │ │ │
  6.                    ╘═══════════════════════════════╛ │ │
  7.                      ────────────────────────────────┘ │
  8.                        ────────────────────────────────┘
  9.  
  10.                            --==[ PART 12 ]==--
  11.  
  12.  
  13.  
  14. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  15. ■ Introduction
  16.  
  17. Hello! :-)
  18.  
  19. Well, a lot has happened since the last trainer, which is the reason for
  20. the amazingly long delay. First, the elections. These were quite easy
  21. actually, I went and watched a move (Demolition Man) (Election day
  22. special, all movies R2, which is about 50 US cents), then went and voted
  23. after most voters had gone home, so no long lines ;-). Soon after were
  24. exams. These did not go too well, and I am not looking forward to the
  25. results. Finally, I got measles and pneumonia at the same time and was
  26. sent off to hospital for a few days. All in all, not events which are
  27. conducive to coding! This has meant that the trainer has been delayed,
  28. and ASPHYXIA was not able to enter into the local democompo, Dexterity
  29. '94, which we were hoping to do well in. Oh well, onward and upward!
  30.  
  31. This trainer is on full screen scrolling in Chain-4, by request. This is
  32. actually very easy to do (and smooth), and holds a lot of potential, as
  33. I am sure you can immediately imagine.
  34.  
  35. A few more things : People have been saying they have had hassles
  36. sending me email, and I have found that this is because they forget the
  37. numbers in my name. They send mail to smith@batis... which does not
  38. exist, or smith@beastie... which is my brothers account. He is getting a
  39. bit sick of forwarding my mail to me ;). The two address are :
  40.        smith9@batis.bis.und.ac.za
  41.        smith0@beastie.cs.und.ac.za
  42.  
  43. I have lost about 200k worth of email, chalk it up to my beginner status
  44. at Unix. The test to see if your mail got through? I have answered
  45. _every_ email message sent to me (no easy task), so if you haven't got a
  46. reply, please resend the message.
  47.  
  48. You can now also send a group message to all members of Asphyxia. Just
  49. send mail to asphyxia@beastie.cs.und.ac.za and we will all get a copy
  50. ... which could mean numerous replies to one querey ;)
  51.  
  52.  
  53. If you would like to contact me, or the team, there are many ways you
  54. can do it : 1) Write a message to Grant Smith/Denthor/Asphyxia in private mail
  55.                   on the ASPHYXIA BBS.
  56.             2) Write to Denthor, EzE, Goth, Fubar or Nobody on Connectix.
  57.             3) Write to :  Grant Smith
  58.                            P.O.Box 270 Kloof
  59.                            3640
  60.                            Natal
  61.                            South Africa
  62.             4) Call me (Grant Smith) at (031) 73 2129 (leave a message if you
  63.                   call during varsity). Call +27-31-73-2129 if you call
  64.                   from outside South Africa. (It's YOUR phone bill ;-))
  65.             5) Write to smith9@batis.bis.und.ac.za in E-Mail.
  66.             6) Write to asphyxia@beastie.cs.und.ac.za
  67.  
  68. NB : If you are a representative of a company or BBS, and want ASPHYXIA
  69.        to do you a demo, leave mail to me; we can discuss it.
  70. NNB : If you have done/attempted a demo, SEND IT TO ME! We are feeling
  71.         quite lonely and want to meet/help out/exchange code with other demo
  72.         groups. What do you have to lose? Leave a message here and we can work
  73.         out how to transfer it. We really want to hear from you!
  74.  
  75.  
  76.  
  77. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  78. ■  What is full screen scrolling?
  79.  
  80. I seem to recall doing this in a previous tut, but here goes again! Full
  81. screen scrolling is when the entire screen moves in a particular
  82. direction, with the new picture scrolling on to the screen. Um. Think of
  83. movie credits. The screen, filled with text, is scrolled off the top of
  84. the screen while the new text is scrolled on from the bottom. This is
  85. full screen scrolling.
  86.  
  87. Full screen scrolling is not limited to movie credits. Games like Raptor
  88. have you flying over a scrolling landscape while you are shooting down
  89. the bad guys. In this tutorial we will be doing vertical scrolling, but
  90. the code can very easily be altered for horizontal scrolling too.
  91.  
  92. Remember that we will be using Chain-4 to do our scrolling, so you may
  93. want to brush up on tut 10 in which that was covered. I will assume a
  94. brief knowledge of how chain-4 works for this tutorial.
  95.  
  96.  
  97. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  98. ■  The theory
  99.  
  100. The theory behind full screen scrolling in Chain-4 is acually very
  101. simple.
  102.  
  103. Picture if you will, a screen that is two monitors high. Chain-4
  104. actually has four, but for this we only need two. Now, for this screen
  105. that is two monitors high, we can only see one monitors worth. Here it
  106. is in ASCII
  107.  
  108.     +-------------+  Screen two monitors high
  109.     |             |
  110.     |             |
  111.     |             |
  112.     |             |
  113.     |+-----------+|
  114.     ||           ||
  115.     ||           ||<- This is the bit we can see, one monitors worth
  116.     ||           ||
  117.     |+-----------+|
  118.     +-------------+
  119.  
  120. We can move the bit we can see up or down the enlarged screen. So, for
  121. example, if the screen two monitors high had a picture on it, we could
  122. move the bit we see up and down to try glimpse the entire picture. Think
  123. of it in this way : The screen is a large painting, but we can only see
  124. though a small magnifing glass. We can move this magnifing glass around
  125. the painting, but can never see the painting all at once.
  126.  
  127. This actually works in our favour. Anything done outside the bit we are
  128. looking through cannot be seen, so we can do our work without changing
  129. our screen.
  130.  
  131. On to scrolling. The method we will use this time is as follows :
  132.  
  133. 1) Draw the next line to be seen just above and just below the part we
  134.    can see.
  135.  
  136.       +------------+ The enlarged screen
  137.       |            |
  138.       |            |
  139.       |111111111111|  The new part of the picture
  140.       |+----------+|
  141.       ||          || The bit we can see
  142.       |+----------+|
  143.       |111111111111|  The new part of the picture
  144.       +------------+
  145.  
  146. 2) Move the view up one pixel so that the new part of the picture is
  147.    visible at the top of the screen.
  148.  
  149. 3) Repeat Steps 1) and 2) until the whole screen is filled. Our screen
  150.    will look as follows :
  151.  
  152.      +---------------+
  153.      |+-------------+|
  154.      ||3333333333333||
  155.      ||2222222222222|| Viewscreen
  156.      ||1111111111111||
  157.      |+-------------+|
  158.      |333333333333333|
  159.      |222222222222222|
  160.      |111111111111111|
  161.      +---------------+
  162.  
  163. Check this picture with steps 1) and 2), you will see that this is
  164. correct.
  165.  
  166. 4) Set our viewport to the bottom of the enlarged screen.
  167.  
  168.      +---------------+
  169.      |333333333333333|
  170.      |222222222222222|
  171.      |111111111111111|
  172.      |+-------------+|
  173.      ||3333333333333||
  174.      ||2222222222222|| New position of viewscreen
  175.      ||1111111111111||
  176.      |+-------------+|
  177.      +---------------+
  178.  
  179. As you can see, the bit we will be looking at is exactly the same as
  180. before, we are now just at the bottom of the larger screen instead of
  181. the top!
  182.  
  183. 5) Jump back to 1). The entire sequence can begin again, and we can have
  184.    infinate scrolling in the upward direction. Clever huh?
  185.  
  186.  
  187. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  188. ■  Our code
  189.  
  190. In the sample code, we have 21 different icons. What we do is decide
  191. what the next row of icons is going to consist of. We then draw the next
  192. line of pixels above and below the viewscreen according to what icons we
  193. are displaying. We then scroll up one pixel and begin again. When we
  194. have completed a row of icons, we randomly select a new row and begin
  195. again. Our icons are 16x16, so exactly 20 fit across a 320 pixel screen.
  196.  
  197. When we hit the top of our enlarged screen, we flip down to the bottom
  198. which looks exactly the same as the screen we have left. In this manner
  199. we have obtained smooth, infinate full screen scrolling!
  200.  
  201.  
  202. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  203. ■  Extra bits
  204.  
  205. As you will see from the code, it would be the work of but a few minutes
  206. to extend our landscape across the two unused screens, thereby allowing
  207. limited horizontal movement along with our vertical movement. In fact,
  208. the entire routine could easily be made to be a horizontal scrolling
  209. routine.
  210.  
  211. A map of sorts could be generated, with one byte equalling one terrain
  212. type. In this manner, the terrain scrolled over could be set, as in a
  213. flying game (Flying Shark, Raptor etc). The terrain could also easily be
  214. replaced with letters for our movie-style credits.
  215.  
  216. Free direction scrolling, ie scrolling in all directions, is a very
  217. different matter, with very different methods to get it to work. Perhaps
  218. this will be discussed in a later trainer. But for now, work with this,
  219. know it, understand it, and think up many great things to do with it!
  220. How about a full screen text scrolly? A game? Go wild!
  221.  
  222.  
  223. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  224. ■  In closing
  225.  
  226. Well, I hope you enjoyed this, the latest trainer. The sample program is
  227. a little short, but that is because the concept is so simple. Attached
  228. is a file, PICCS.DAT, which contains the terrain and letters for the
  229. sample program. They were .CEL's, which I loaded into the des^ variable,
  230. which I then dumped to disk, for easy access later. The .CEL's were
  231. drawn on short notice, but still produces some nice terrain.
  232.  
  233. I have recieved a few requests for future trainers, and most of them are
  234. for effects, so I guess that is what will be done from now on. A
  235. surprising number have told me not to do a sound trainer and stick with
  236. graphics stuff, with only a few asking for sound stuff, so I will hold
  237. off on that until there is more of a demand.
  238.  
  239. I am still open to suggestions for future trainers, and of course
  240. suggestions for improving the series. Leave me mail!
  241.  
  242. Hmm. A quote? Okay, let me think ....
  243.  
  244.         [    The little devil sat atop the alpine slopes, frolicking in the
  245.            snow.  He threw a snowball at a nearby squirrel, which
  246.            missed. The resulting avalance buried two villages and a ski
  247.            resort.
  248.              The little devil was scared. Avalances were bad for
  249.            business. The locals would form team spirit, be nice to
  250.            each other and work together and free those trapped beneath
  251.            the snow, which created even more goodwill. The man
  252.            downstairs didn't like goodwill. He didn't like it at
  253.            all.
  254.              In the blink of an eye the devil was in his penthouse
  255.            apartment, dressed in his usual suit. He picked up the phone.
  256.            Dialing was for mortals.
  257.              "Hello, Micros..."
  258.              "This is Mister Crowley", interrupted the devil.
  259.              There were sounds of thumping on the other side of the
  260.            phone, then there was a new voice. "Hello, Bill here, we
  261.            haven't heard from you in a while, Mister Crowley." The fear
  262.            of the man on the other end was almost tangible. The devil
  263.            smiled.
  264.              "Hello Bill. Something has come up."
  265.              "No!" The man on the other side almost shouted with terror.
  266.            "Not Win..."
  267.              "Yes, Bill. It is time."
  268.              "Havn't I paid enough for my sins? Just that one night..."
  269.            The man was almost sobbing.
  270.              "You are touching me, Bill. But nevertheless, it is time."
  271.              "No." The man sounded beaten, alone.
  272.              "Yes. Bill, it is time for a new update."
  273.                                                                        ]
  274.                                                       - Grant Smith
  275.                                                           14:23
  276.                                                             23-7-94
  277.  
  278. See you next time!
  279.   - Denthor
  280.  
  281. The following are official ASPHYXIA distribution sites :
  282.  
  283. ╔══════════════════════════╦════════════════╦═════╗
  284. ║BBS Name                  ║Telephone No.   ║Open ║
  285. ╠══════════════════════════╬════════════════╬═════╣
  286. ║ASPHYXIA BBS #1           ║+27-31-765-5312 ║ALL  ║
  287. ║ASPHYXIA BBS #2           ║+27-31-765-6293 ║ALL  ║
  288. ║C-Spam BBS                ║410-531-5886    ║ALL  ║
  289. ║Connectix BBS             ║+27-31-266-9992 ║ALL  ║
  290. ║POP!                      ║+27-12-661-1257 ║ALL  ║
  291. ║Pure Surf BBS             ║+27-31-561-5943 ║A/H  ║
  292. ║Soul Asylum               ║+358-0-5055041  ║ALL  ║
  293. ║Wasted Image              ║407-838-4525    ║ALL  ║
  294. ╚══════════════════════════╩════════════════╩═════╝
  295.  
  296. Leave me mail if you want to become an official Asphyxia BBS
  297. distribution site.
  298.  
  299.  
  300. Unit GFX2;
  301.  
  302.  
  303. INTERFACE
  304.  
  305. USES crt;
  306. CONST VGA = $A000;
  307.  
  308. TYPE Virtual = Array [1..64000] of byte;  { The size of our Virtual Screen }
  309.      VirtPtr = ^Virtual;                  { Pointer to the virtual screen }
  310.  
  311. VAR Virscr : VirtPtr;                     { Our first Virtual screen }
  312.     Vaddr  : word;                        { The segment of our virtual screen}
  313.  
  314. Procedure SetMCGA;
  315.    { This procedure gets you into 320x200x256 mode. }
  316. Procedure SetText;
  317.    { This procedure returns you to text mode.  }
  318. Procedure Cls (Where:word;Col : Byte);
  319.    { This clears the screen to the specified color }
  320. Procedure SetUpVirtual;
  321.    { This sets up the memory needed for the virtual screen }
  322. Procedure ShutDown;
  323.    { This frees the memory used by the virtual screen }
  324. procedure flip(source,dest:Word);
  325.    { This copies the entire screen at "source" to destination }
  326. Procedure Pal(Col,R,G,B : Byte);
  327.    { This sets the Red, Green and Blue values of a certain color }
  328. Procedure GetPal(Col : Byte; Var R,G,B : Byte);
  329.   { This gets the Red, Green and Blue values of a certain color }
  330. procedure WaitRetrace;
  331.    {  This waits for a vertical retrace to reduce snow on the screen }
  332. Procedure Hline (x1,x2,y:word;col:byte;where:word);
  333.    { This draws a horizontal line from x1 to x2 on line y in color col }
  334. Procedure Line(a,b,c,d:integer;col:byte;where:word);
  335.   { This draws a solid line from a,b to c,d in colour col }
  336. Procedure DrawPoly(x1,y1,x2,y2,x3,y3,x4,y4:integer;color:byte;where:word);
  337.    { This draw a polygon with 4 points at x1,y1 , x2,y2 , x3,y3 , x4,y4
  338.      in color col }
  339. Function rad (theta : real) : real;
  340.    {  This calculates the degrees of an angle }
  341. Procedure Putpixel (X,Y : Integer; Col : Byte; where:word);
  342.    { This puts a pixel on the screen by writing directly to memory. }
  343. Function Getpixel (X,Y : Integer; where:word) :Byte;
  344.    { This gets the pixel on the screen by reading directly to memory. }
  345. Procedure LoadCEL (FileName :  string; ScrPtr : pointer);
  346.   { This loads the cel 'filename' into the pointer scrptr }
  347.  
  348.  
  349. IMPLEMENTATION
  350.  
  351. {──────────────────────────────────────────────────────────────────────────}
  352. Procedure SetMCGA;  { This procedure gets you into 320x200x256 mode. }
  353. BEGIN
  354.   asm
  355.      mov        ax,0013h
  356.      int        10h
  357.   end;
  358. END;
  359.  
  360. {──────────────────────────────────────────────────────────────────────────}
  361. Procedure SetText;  { This procedure returns you to text mode.  }
  362. BEGIN
  363.   asm
  364.      mov        ax,0003h
  365.      int        10h
  366.   end;
  367. END;
  368.  
  369. {──────────────────────────────────────────────────────────────────────────}
  370. Procedure Cls (Where:word;Col : Byte); assembler;
  371.    { This clears the screen to the specified color }
  372. asm
  373.    push    es
  374.    mov     cx, 32000;
  375.    mov     es,[where]
  376.    xor     di,di
  377.    mov     al,[col]
  378.    mov     ah,al
  379.    rep     stosw
  380.    pop     es
  381. End;
  382.  
  383. {──────────────────────────────────────────────────────────────────────────}
  384. Procedure SetUpVirtual;
  385.    { This sets up the memory needed for the virtual screen }
  386. BEGIN
  387.   GetMem (VirScr,64000);
  388.   vaddr := seg (virscr^);
  389. END;
  390.  
  391. {──────────────────────────────────────────────────────────────────────────}
  392. Procedure ShutDown;
  393.    { This frees the memory used by the virtual screen }
  394. BEGIN
  395.   FreeMem (VirScr,64000);
  396. END;
  397.  
  398. {──────────────────────────────────────────────────────────────────────────}
  399. procedure flip(source,dest:Word); assembler;
  400.   { This copies the entire screen at "source" to destination }
  401. asm
  402.   push    ds
  403.   mov     ax, [Dest]
  404.   mov     es, ax
  405.   mov     ax, [Source]
  406.   mov     ds, ax
  407.   xor     si, si
  408.   xor     di, di
  409.   mov     cx, 32000
  410.   rep     movsw
  411.   pop     ds
  412. end;
  413.  
  414. {──────────────────────────────────────────────────────────────────────────}
  415. Procedure Pal(Col,R,G,B : Byte); assembler;
  416.   { This sets the Red, Green and Blue values of a certain color }
  417. asm
  418.    mov    dx,3c8h
  419.    mov    al,[col]
  420.    out    dx,al
  421.    inc    dx
  422.    mov    al,[r]
  423.    out    dx,al
  424.    mov    al,[g]
  425.    out    dx,al
  426.    mov    al,[b]
  427.    out    dx,al
  428. end;
  429.  
  430. {──────────────────────────────────────────────────────────────────────────}
  431. Procedure GetPal(Col : Byte; Var R,G,B : Byte);
  432.   { This gets the Red, Green and Blue values of a certain color }
  433. Var
  434.    rr,gg,bb : Byte;
  435. Begin
  436.    asm
  437.       mov    dx,3c7h
  438.       mov    al,col
  439.       out    dx,al
  440.  
  441.       add    dx,2
  442.  
  443.       in     al,dx
  444.       mov    [rr],al
  445.       in     al,dx
  446.       mov    [gg],al
  447.       in     al,dx
  448.       mov    [bb],al
  449.    end;
  450.    r := rr;
  451.    g := gg;
  452.    b := bb;
  453. end;
  454.  
  455. {──────────────────────────────────────────────────────────────────────────}
  456. procedure WaitRetrace; assembler;
  457.   {  This waits for a vertical retrace to reduce snow on the screen }
  458. label
  459.   l1, l2;
  460. asm
  461.     mov dx,3DAh
  462. l1:
  463.     in al,dx
  464.     and al,08h
  465.     jnz l1
  466. l2:
  467.     in al,dx
  468.     and al,08h
  469.     jz  l2
  470. end;
  471.  
  472. {──────────────────────────────────────────────────────────────────────────}
  473. Procedure Hline (x1,x2,y:word;col:byte;where:word); assembler;
  474.   { This draws a horizontal line from x1 to x2 on line y in color col }
  475. asm
  476.   mov   ax,where
  477.   mov   es,ax
  478.   mov   ax,y
  479.   mov   di,ax
  480.   shl   ax,8
  481.   shl   di,6
  482.   add   di,ax
  483.   add   di,x1
  484.  
  485.   mov   al,col
  486.   mov   ah,al
  487.   mov   cx,x2
  488.   sub   cx,x1
  489.   shr   cx,1
  490.   jnc   @start
  491.   stosb
  492. @Start :
  493.   rep   stosw
  494. end;
  495.  
  496. {──────────────────────────────────────────────────────────────────────────}
  497. Procedure Line(a,b,c,d:integer;col:byte;where:word);
  498.   { This draws a solid line from a,b to c,d in colour col }
  499.   function sgn(a:real):integer;
  500.   begin
  501.        if a>0 then sgn:=+1;
  502.        if a<0 then sgn:=-1;
  503.        if a=0 then sgn:=0;
  504.   end;
  505. var i,s,d1x,d1y,d2x,d2y,u,v,m,n:integer;
  506. begin
  507.      u:= c - a;
  508.      v:= d - b;
  509.      d1x:= SGN(u);
  510.      d1y:= SGN(v);
  511.      d2x:= SGN(u);
  512.      d2y:= 0;
  513.      m:= ABS(u);
  514.      n := ABS(v);
  515.      IF NOT (M>N) then
  516.      BEGIN
  517.           d2x := 0 ;
  518.           d2y := SGN(v);
  519.           m := ABS(v);
  520.           n := ABS(u);
  521.      END;
  522.      s := m shr 1;
  523.      FOR i := 0 TO m DO
  524.      BEGIN
  525.           putpixel(a,b,col,where);
  526.           s := s + n;
  527.           IF not (s<m) THEN
  528.           BEGIN
  529.                s := s - m;
  530.                a:= a + d1x;
  531.                b := b + d1y;
  532.           END
  533.           ELSE
  534.           BEGIN
  535.                a := a + d2x;
  536.                b := b + d2y;
  537.           END;
  538.      end;
  539. END;
  540.  
  541.  
  542. {──────────────────────────────────────────────────────────────────────────}
  543. Procedure DrawPoly(x1,y1,x2,y2,x3,y3,x4,y4:integer;color:byte;where:word);
  544.   { This draw a polygon with 4 points at x1,y1 , x2,y2 , x3,y3 , x4,y4
  545.     in color col }
  546. var
  547.   x:integer;
  548.   mny,mxy:integer;
  549.   mnx,mxx,yc:integer;
  550.   mul1,div1,
  551.   mul2,div2,
  552.   mul3,div3,
  553.   mul4,div4:integer;
  554.  
  555. begin
  556.   mny:=y1; mxy:=y1;
  557.   if y2<mny then mny:=y2;
  558.   if y2>mxy then mxy:=y2;
  559.   if y3<mny then mny:=y3;
  560.   if y3>mxy then mxy:=y3;    { Choose the min y mny and max y mxy }
  561.   if y4<mny then mny:=y4;
  562.   if y4>mxy then mxy:=y4;
  563.  
  564.   if mny<0 then mny:=0;
  565.   if mxy>199 then mxy:=199;
  566.   if mny>199 then exit;
  567.   if mxy<0 then exit;        { Verticle range checking }
  568.  
  569.   mul1:=x1-x4; div1:=y1-y4;
  570.   mul2:=x2-x1; div2:=y2-y1;
  571.   mul3:=x3-x2; div3:=y3-y2;
  572.   mul4:=x4-x3; div4:=y4-y3;  { Constansts needed for intersection calc }
  573.  
  574.   for yc:=mny to mxy do
  575.     begin
  576.       mnx:=320;
  577.       mxx:=-1;
  578.       if (y4>=yc) or (y1>=yc) then
  579.         if (y4<=yc) or (y1<=yc) then   { Check that yc is between y1 and y4 }
  580.           if not(y4=y1) then
  581.             begin
  582.               x:=(yc-y4)*mul1 div div1+x4; { Point of intersection on x axis }
  583.               if x<mnx then
  584.                 mnx:=x;
  585.               if x>mxx then
  586.                 mxx:=x;       { Set point as start or end of horiz line }
  587.             end;
  588.       if (y1>=yc) or (y2>=yc) then
  589.         if (y1<=yc) or (y2<=yc) then   { Check that yc is between y1 and y2 }
  590.           if not(y1=y2) then
  591.             begin
  592.               x:=(yc-y1)*mul2 div div2+x1; { Point of intersection on x axis }
  593.               if x<mnx then
  594.                 mnx:=x;
  595.               if x>mxx then
  596.                 mxx:=x;       { Set point as start or end of horiz line }
  597.             end;
  598.       if (y2>=yc) or (y3>=yc) then
  599.         if (y2<=yc) or (y3<=yc) then   { Check that yc is between y2 and y3 }
  600.           if not(y2=y3) then
  601.             begin
  602.               x:=(yc-y2)*mul3 div div3+x2; { Point of intersection on x axis }
  603.               if x<mnx then
  604.                 mnx:=x;
  605.               if x>mxx then
  606.                 mxx:=x;       { Set point as start or end of horiz line }
  607.             end;
  608.       if (y3>=yc) or (y4>=yc) then
  609.         if (y3<=yc) or (y4<=yc) then   { Check that yc is between y3 and y4 }
  610.           if not(y3=y4) then
  611.             begin
  612.               x:=(yc-y3)*mul4 div div4+x3; { Point of intersection on x axis }
  613.               if x<mnx then
  614.                 mnx:=x;
  615.               if x>mxx then
  616.                 mxx:=x;       { Set point as start or end of horiz line }
  617.             end;
  618.       if mnx<0 then
  619.         mnx:=0;
  620.       if mxx>319 then
  621.         mxx:=319;          { Range checking on horizontal line }
  622.       if mnx<=mxx then
  623.         hline (mnx,mxx,yc,color,where);   { Draw the horizontal line }
  624.     end;
  625.   end;
  626.  
  627. {──────────────────────────────────────────────────────────────────────────}
  628. Function rad (theta : real) : real;
  629.   {  This calculates the degrees of an angle }
  630. BEGIN
  631.   rad := theta * pi / 180
  632. END;
  633.  
  634. {──────────────────────────────────────────────────────────────────────────}
  635. Procedure Putpixel (X,Y : Integer; Col : Byte; where:word); assembler;
  636.   { This puts a pixel on the screen by writing directly to memory. }
  637. Asm
  638.   mov     ax,[where]
  639.   mov     es,ax
  640.   mov     bx,[X]
  641.   mov     dx,[Y]
  642.   mov     di,bx
  643.   mov     bx, dx                  {; bx = dx}
  644.   shl     dx, 8
  645.   shl     bx, 6
  646.   add     dx, bx                  {; dx = dx + bx (ie y*320)}
  647.   add     di, dx                  {; finalise location}
  648.   mov     al, [Col]
  649.   stosb
  650. End;
  651.  
  652. {──────────────────────────────────────────────────────────────────────────}
  653. Function Getpixel (X,Y : Integer; where:word):byte; assembler;
  654.   { This puts a pixel on the screen by writing directly to memory. }
  655. Asm
  656.   mov     ax,[where]
  657.   mov     es,ax
  658.   mov     bx,[X]
  659.   mov     dx,[Y]
  660.   mov     di,bx
  661.   mov     bx, dx                  {; bx = dx}
  662.   shl     dx, 8
  663.   shl     bx, 6
  664.   add     dx, bx                  {; dx = dx + bx (ie y*320)}
  665.   add     di, dx                  {; finalise location}
  666.   mov     al, es:[di]
  667. End;
  668.  
  669. {──────────────────────────────────────────────────────────────────────────}
  670. Procedure LoadCEL (FileName :  string; ScrPtr : pointer);
  671.   { This loads the cel 'filename' into the pointer scrptr }
  672. var
  673.   Fil : file;
  674.   Buf : array [1..1024] of byte;
  675.   BlocksRead, Count : word;
  676. begin
  677.   assign (Fil, FileName);
  678.   reset (Fil, 1);
  679.   BlockRead (Fil, Buf, 800);    { Read and ignore the 800 byte header }
  680.   Count := 0; BlocksRead := $FFFF;
  681.   while (not eof (Fil)) and (BlocksRead <> 0) do begin
  682.     BlockRead (Fil, mem [seg (ScrPtr^): ofs (ScrPtr^) + Count], 1024, BlocksRead);
  683.     Count := Count + 1024;
  684.   end;
  685.   close (Fil);
  686. end;
  687.  
  688.  
  689.  
  690.  
  691. BEGIN
  692. END.{$X+}
  693. Uses Crt,GFX2;
  694.  
  695. Const Size : Byte = 80;      { Size =  40 = 1 across, 4 down }
  696.                              { Size =  80 = 2 across, 2 down }
  697.                              { Size = 160 = 4 across, 1 down }
  698.  
  699. Type Icon = Array [1..256] of byte;
  700.      Terrain = Array [1..21] of Icon;  {base 8 are desert, top 13 are letters }
  701.  
  702. VAR des : ^Terrain;       { Desert}
  703.  
  704.  
  705. {──────────────────────────────────────────────────────────────────────────}
  706. Procedure InitChain4; ASSEMBLER;
  707.   {  This procedure gets you into Chain 4 mode }
  708. Asm
  709.     mov    ax, 13h
  710.     int    10h         { Get into MCGA Mode }
  711.  
  712.     mov    dx, 3c4h    { Port 3c4h = Sequencer Address Register }
  713.     mov    al, 4       { Index 4 = memory mode }
  714.     out    dx, al
  715.     inc    dx          { Port 3c5h ... here we set the mem mode }
  716.     in     al, dx
  717.     and    al, not 08h
  718.     or     al, 04h
  719.     out    dx, al
  720.     mov    dx, 3ceh
  721.     mov    al, 5
  722.     out    dx, al
  723.     inc    dx
  724.     in     al, dx
  725.     and    al, not 10h
  726.     out    dx, al
  727.     dec    dx
  728.     mov    al, 6
  729.     out    dx, al
  730.     inc    dx
  731.     in     al, dx
  732.     and    al, not 02h
  733.     out    dx, al
  734.     mov    dx, 3c4h
  735.     mov    ax, (0fh shl 8) + 2
  736.     out    dx, ax
  737.     mov    ax, 0a000h
  738.     mov    es, ax
  739.     sub    di, di
  740.     mov    ax, 0000h {8080h}
  741.     mov    cx, 32768
  742.     cld
  743.     rep    stosw            { Clear garbage off the screen ... }
  744.  
  745.     mov    dx, 3d4h
  746.     mov    al, 14h
  747.     out    dx, al
  748.     inc    dx
  749.     in     al, dx
  750.     and    al, not 40h
  751.     out    dx, al
  752.     dec    dx
  753.     mov    al, 17h
  754.     out    dx, al
  755.     inc    dx
  756.     in     al, dx
  757.     or     al, 40h
  758.     out    dx, al
  759.  
  760.     mov    dx, 3d4h
  761.     mov    al, 13h
  762.     out    dx, al
  763.     inc    dx
  764.     mov    al, [Size]      { Size * 8 = Pixels across. Only 320 are visible}
  765.     out    dx, al
  766. End;
  767.  
  768.  
  769. {──────────────────────────────────────────────────────────────────────────}
  770. Procedure C4PutPixel(X,Y : Word; Col : Byte); ASSEMBLER;
  771.   { This puts a pixel on the chain 4 screen }
  772. Asm
  773.     mov    ax,[y]
  774.     xor    bx,bx
  775.     mov    bl,[size]
  776.     imul   bx
  777.     shl    ax,1
  778.     mov    bx,ax
  779.     mov    ax, [X]
  780.     mov    cx, ax
  781.     shr    ax, 2
  782.     add    bx, ax
  783.     and    cx, 00000011b
  784.     mov    ah, 1
  785.     shl    ah, cl
  786.     mov    dx, 3c4h                  { Sequencer Register    }
  787.     mov    al, 2                     { Map Mask Index        }
  788.     out    dx, ax
  789.  
  790.     mov    ax, 0a000h
  791.     mov    es, ax
  792.     mov    al, [col]
  793.     mov    es: [bx], al
  794. End;
  795.  
  796. {──────────────────────────────────────────────────────────────────────────}
  797. Procedure Plane(Which : Byte); ASSEMBLER;
  798.   { This sets the plane to write to in Chain 4}
  799. Asm
  800.    mov     al, 2h
  801.    mov     ah, 1
  802.    mov     cl, [Which]
  803.    shl     ah, cl
  804.    mov     dx, 3c4h                  { Sequencer Register    }
  805.    out     dx, ax
  806. End;
  807.  
  808.  
  809. {──────────────────────────────────────────────────────────────────────────}
  810. procedure moveto(x, y : word);
  811.   { This moves to position x*4,y on a chain 4 screen }
  812. var o : word;
  813. begin
  814.   o := y*size*2+x;
  815.   asm
  816.     mov    bx, [o]
  817.     mov    ah, bh
  818.     mov    al, 0ch
  819.  
  820.     mov    dx, 3d4h
  821.     out    dx, ax
  822.  
  823.     mov    ah, bl
  824.     mov    al, 0dh
  825.     mov    dx, 3d4h
  826.     out    dx, ax
  827.   end;
  828. end;
  829.  
  830.  
  831. {──────────────────────────────────────────────────────────────────────────}
  832. procedure LoadPal (FileName : string);
  833.   { This loads .col file and sets the pallette }
  834. type
  835.   DACType = array [0..255,1..3] of byte;
  836. var
  837.   DAC : DACType;
  838.   Fil : file of DACType;
  839.   I : integer;
  840. begin
  841.   assign (Fil, FileName);
  842.   reset (Fil);
  843.   read (Fil, DAC);
  844.   close (Fil);
  845.   for I := 0 to 255 do
  846.     pal (i,dac[i,1],dac[i,2],dac[i,3]);
  847. end;
  848.  
  849.  
  850. {──────────────────────────────────────────────────────────────────────────}
  851. Procedure Init;
  852.   { We get our memory and load the graphics here }
  853. VAR f:file;
  854. BEGIN
  855.   Getmem (des,sizeof (des^));
  856.   assign (f,'piccs.dat');
  857.   reset (f,1);
  858.   blockread (f,des^,sizeof(des^));
  859.   close (f);
  860.   loadpal ('pallette.col');
  861. END;
  862.  
  863.  
  864. {──────────────────────────────────────────────────────────────────────────}
  865. Procedure Play;
  866.   { Our main procedure }
  867. CONST sAsp : Array [0..19] of byte =
  868. (1,3,2,4,5,3,9,10,11,12,13,14,15,9,7,4,5,2,1,4);   { Data for 'ASPHYXIA' }
  869.       sVGA : Array [0..19] of byte =
  870. (4,7,1,2,4,5,8,3,16,17,9,5,6,2,5,8,6,2,5,7);       { Data for 'VGA' }
  871.       sTra : Array [0..19] of byte =
  872. (2,5,8,2,1,6,18,19,9,15,20,21,19,7,2,4,1,8,3,4);   { Data for 'TRAINER' }
  873.  
  874. Var loop1,loop2:integer;
  875.     depth,farin:integer;
  876.     what:array[0..19] of byte;
  877.     count:integer;
  878. Begin
  879.    MoveTo(0,200); { This moves the view to the left hand corner }
  880.    depth:=200;    { This is our y for our viewport }
  881.    farin:=15;     { This is how far in to the icon we have drawn }
  882.    count:=0;      { This is for when the write ASPHYXIA VGA TRAINER }
  883.    for loop1:=0 to 19 do what[loop1]:=random (8)+1;
  884.         { This sets a random row of desert icons }
  885.    Repeat
  886.      for loop1:=0 to 19 do
  887.        for loop2:=0 to 15 do BEGIN
  888.          c4putpixel (loop1*16+loop2,depth,des^[what[loop1],farin*16+loop2+1]);
  889.          c4putpixel (loop1*16+loop2,depth+201,des^[what[loop1],farin*16+loop2+1]);
  890.        END;
  891.         { This draws the two rows of pixels, above and below the viewport }
  892.      depth:=depth-1; { This moves our viewport up one pixel }
  893.      farin:=farin-1; { This moves us to the next row in our icons }
  894.      if depth=-1 then depth:=200; {We have hit the top, jump to the bottom }
  895.      if farin=-1 then BEGIN { We have finished our row of icons }
  896.        farin:=15;
  897.        for loop1:=0 to 19 do what[loop1]:=random (8)+1;
  898.          { This sets a random row of desert icons }
  899.        inc (count);
  900.        if count=24 then for loop1:=0 to 19 do what[loop1]:=sasp[loop1];
  901.        if count=22 then for loop1:=0 to 19 do what[loop1]:=svga[loop1];
  902.        if count=20 then for loop1:=0 to 19 do what[loop1]:=stra[loop1];
  903.        if count=50 then count:=0;
  904.      END;
  905.      waitretrace;
  906.      moveto(0,depth);
  907.    Until keypressed;
  908.    Readkey;
  909. End;
  910.  
  911.  
  912. BEGIN
  913.   clrscr;
  914.   Writeln ('Hello! After a long absence, here is the latest installment of the');
  915.   Writeln ('ASPHYXIA VGA Trainer! This one, by popular demand, is on full screen');
  916.   WRiteln ('scrolling in Chain-4. This isn''t very interactive, just hit any key');
  917.   Writeln ('and a random landscape will scroll by for infinity, with the letters');
  918.   Writeln ('ASPHYXIA VGA TRAINER scrolling passed at set intervals. You will notice');
  919.   Writeln ('that two of our four pages are untouched. These could be put to good');
  920.   Writeln ('use in for example a game etc.');
  921.   Writeln;
  922.   Writeln ('This code could easily be altered to produce a movie-credits type');
  923.   Writeln ('sequence, a large game-map and so on. Have fun with it and see what');
  924.   Writeln ('you can come up with! All desert art is done by Pieter Buys (Fubar), may');
  925.   Writeln ('I add on very short notice by my request. The font was, I think, ripped,');
  926.   Writeln ('I found it lying about on my hard drive.');
  927.   Writeln;
  928.   Writeln ('The code is very easy to follow and you should have it doing what you want');
  929.   Writeln ('in no time.');
  930.   writeln;
  931.   writeln;
  932.   Write ('  Hit any key to contine ...');
  933.   Readkey;
  934.   initChain4;
  935.   init;
  936.   play;
  937.   Freemem (des,sizeof (des^));
  938.   SetText;
  939.   Writeln ('All done. This concludes the twelfth sample program in the ASPHYXIA');
  940.   Writeln ('Training series. You may reach DENTHOR under the names of GRANT');
  941.   Writeln ('SMITH/DENTHOR/ASPHYXIA on the ASPHYXIA BBS. I am also an avid');
  942.   Writeln ('Connectix BBS user, and occasionally read RSAProg. E-mail me at :');
  943.   Writeln ('    smith9@batis.bis.und.ac.za');
  944.   Writeln ('The numbers are available in the main text. You may also write to me at:');
  945.   Writeln ('             Grant Smith');
  946.   Writeln ('             P.O. Box 270');
  947.   Writeln ('             Kloof');
  948.   Writeln ('             3640');
  949.   Writeln ('             Natal');
  950.   Writeln ('             South Africa');
  951.   Writeln ('I hope to hear from you soon!');
  952.   Writeln; Writeln;
  953.   Write   ('Hit any key to exit ...');
  954.   Readkey;
  955. END.